{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "# ObjectClassクラス\n",
    "\n",
    "* ObjectClassクラス\n",
    "    * Objectクラスのスーパークラス\n",
    "    * 特殊な用途のために用意されているクラス\n",
    "        * Objectクラスで定義されているメソッドが多すぎるときなど"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "# Objectクラス\n",
    "\n",
    "* Objectクラス\n",
    "    * 全てのクラスのスーパークラス\n",
    "    * Kernelモジュールをincludeしている\n",
    "        * 全てのオブジェクトでKernelモジュールのメソッドを使用できる\n",
    "        "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "## オブジェクトID\n",
    "\n",
    "* オブジェクトID\n",
    "    * オブジェクトに割り当てられている重複しない整数\n",
    "    * 同じオブジェクトであれば同じ値になる\n",
    "* Rubyはすべてオブジェクト\n",
    "    * 同じリテラルであっても基本的にオブジェクトIDは異なる\n",
    "    * 例外\n",
    "        * 以下のクラスのインスタンスは同じリテラルであれば同じオブジェクト(オブジェクトID)\n",
    "            * TrueClass\n",
    "            * FlaseClass\n",
    "            * NilClass\n",
    "            * Symbol\n",
    "            * Fixnum"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "70121687943080\n",
      "70121687943080\n"
     ]
    }
   ],
   "source": [
    "foo = \"bar\"\n",
    "puts foo.object_id\n",
    "puts foo.__id__"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "StringクラスのインスタンスのオブジェクトIDは毎回異なる\n",
      "70121695856640\n",
      "70121695839040\n",
      "SymbolクラスのインスタンスのオブジェクトIDは毎回異なる\n",
      "3190108\n",
      "3190108\n"
     ]
    }
   ],
   "source": [
    "puts \"StringクラスのインスタンスのオブジェクトIDは毎回異なる\"\n",
    "puts \"foo\".object_id\n",
    "puts \"foo\".object_id\n",
    "\n",
    "puts \"SymbolクラスのインスタンスのオブジェクトIDは毎回異なる\"\n",
    "puts :foo.object_id\n",
    "puts :foo.object_id\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "## オブジェクトのクラス\n",
    "\n",
    "classというメソッドで調べる"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "String\n",
      "Symbol\n"
     ]
    }
   ],
   "source": [
    "puts \"foo\".class\n",
    "puts :foo.class"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "## オブジェクトの比較\n",
    "\n",
    "* クラスによらない\n",
    "    * equal?\n",
    "        * オブジェクトIDを比較する\n",
    "    * eql?\n",
    "        * ハッシュのキーが同じかを比較する\n",
    "* クラスによる (クラスで再定義される)\n",
    "    * ==\n",
    "        * オブジェクトの内容が同じかどうかを比較する\n",
    "        * Stringクラスの場合eql?と同じ\n",
    "    * ===\n",
    "        * case文での比較に用いられる"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "ハッシュの値\n",
      "a.hash = 643637397959947742\n",
      "b.hash = 643637397959947742\n",
      "c.hash = 9969\n",
      "d.hash = 9969\n",
      "オブジェクトID\n",
      "a.object_id = 70121692612980\n",
      "b.object_id = 70121692612960\n",
      "c.object_id = 3190108\n",
      "d.object_id = 3190108\n",
      "\n",
      "aとbのハッシュは同じ\n",
      "true\n",
      "aとbのオブジェクトIDは異なる\n",
      "false\n",
      "cとdのオブジェクトIDは同じ\n",
      "true\n"
     ]
    }
   ],
   "source": [
    "a = \"foo\"\n",
    "b = \"foo\"\n",
    "c = :foo\n",
    "d = :foo\n",
    "\n",
    "puts \"ハッシュの値\"\n",
    "puts \"a.hash = #{a.hash}\"\n",
    "puts \"b.hash = #{b.hash}\"\n",
    "puts \"c.hash = #{c.hash}\"\n",
    "puts \"d.hash = #{d.hash}\"\n",
    "puts \"オブジェクトID\"\n",
    "puts \"a.object_id = #{a.object_id}\"\n",
    "puts \"b.object_id = #{b.object_id}\"\n",
    "puts \"c.object_id = #{c.object_id}\"\n",
    "puts \"d.object_id = #{d.object_id}\"\n",
    "puts \"\"\n",
    "\n",
    "puts \"aとbのハッシュは同じ\"\n",
    "puts a.eql?(b)\n",
    "puts \"aとbのオブジェクトIDは異なる\"\n",
    "puts a.equal?(b)\n",
    "puts \"cとdのオブジェクトIDは同じ\"\n",
    "puts c.equal?(d)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "## オブジェクトのメソッド一覧\n",
    "\n",
    "* methods\n",
    "    * publicメソッドとprivateメソッド\n",
    "* private_methods\n",
    "    * privateメソッド\n",
    "* protected_methods\n",
    "    * protectedメソッド\n",
    "* public_methods\n",
    "    * publicメソッド\n",
    "* singleton_methods\n",
    "    * singletonメソッド"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "publicメソッドとprivateメソッド\n",
      "[:include?, :unicode_normalize, :%, :to_c, :unicode_normalize!, :unicode_normalized?, :*, :+, :shellsplit, :shellescape, :count, :partition, :unpack, :encode, :encode!, :next, :casecmp, :insert, :bytesize, :match, :succ!, :next!, :upto, :index, :rindex, :replace, :clear, :chr, :+@, :-@, :setbyte, :getbyte, :<=>, :<<, :scrub, :scrub!, :byteslice, :==, :===, :dump, :=~, :downcase, :[], :[]=, :upcase, :downcase!, :capitalize, :swapcase, :upcase!, :oct, :empty?, :eql?, :hex, :chars, :split, :capitalize!, :swapcase!, :concat, :codepoints, :reverse, :lines, :bytes, :prepend, :scan, :ord, :reverse!, :center, :sub, :freeze, :inspect, :intern, :end_with?, :gsub, :chop, :crypt, :gsub!, :start_with?, :rstrip, :sub!, :ljust, :length, :size, :strip!, :succ, :rstrip!, :chomp, :strip, :rjust, :lstrip!, :tr!, :chomp!, :squeeze, :lstrip, :tr_s!, :to_str, :to_sym, :chop!, :each_byte, :each_char, :each_codepoint, :to_s, :to_i, :tr_s, :delete, :encoding, :force_encoding, :sum, :delete!, :squeeze!, :tr, :to_f, :valid_encoding?, :slice, :slice!, :rpartition, :each_line, :b, :ascii_only?, :hash, :to_r, :to_json, :to_json_raw, :to_json_raw_object, :<, :>, :<=, :>=, :between?, :pry, :__binding__, :pretty_print, :pretty_print_cycle, :pretty_print_instance_variables, :pretty_print_inspect, :instance_of?, :public_send, :instance_variable_get, :instance_variable_set, :instance_variable_defined?, :remove_instance_variable, :private_methods, :kind_of?, :instance_variables, :tap, :define_singleton_method, :is_a?, :extend, :to_enum, :enum_for, :pretty_inspect, :!~, :respond_to?, :display, :object_id, :send, :gem, :method, :public_method, :singleton_method, :nil?, :class, :singleton_class, :clone, :dup, :itself, :taint, :tainted?, :untaint, :untrust, :trust, :untrusted?, :methods, :protected_methods, :frozen?, :public_methods, :singleton_methods, :!, :!=, :__send__, :equal?, :instance_eval, :instance_exec, :__id__]\n",
      "privateメソッド\n",
      "[:initialize, :initialize_copy, :timeout, :Digest, :DelegateClass, :sprintf, :format, :Integer, :Float, :String, :Array, :Hash, :catch, :throw, :loop, :block_given?, :Rational, :Complex, :trace_var, :untrace_var, :JSON, :at_exit, :jj, :set_trace_func, :caller, :caller_locations, :select, :test, :fork, :exit, :`, :gem_original_require, :j, :sleep, :pp, :URI, :respond_to_missing?, :load, :exec, :exit!, :system, :spawn, :abort, :open, :syscall, :print, :printf, :puts, :putc, :readlines, :Pathname, :p, :readline, :gets, :srand, :rand, :proc, :lambda, :initialize_clone, :initialize_dup, :trap, :require, :require_relative, :autoload, :autoload?, :binding, :local_variables, :warn, :raise, :fail, :global_variables, :__method__, :__callee__, :__dir__, :eval, :iterator?, :method_missing, :singleton_method_added, :singleton_method_removed, :singleton_method_undefined]\n",
      "protectedメソッド\n",
      "[]\n",
      "publicメソッド\n",
      "[:include?, :unicode_normalize, :%, :to_c, :unicode_normalize!, :unicode_normalized?, :*, :+, :shellsplit, :shellescape, :count, :partition, :unpack, :encode, :encode!, :next, :casecmp, :insert, :bytesize, :match, :succ!, :next!, :upto, :index, :rindex, :replace, :clear, :chr, :+@, :-@, :setbyte, :getbyte, :<=>, :<<, :scrub, :scrub!, :byteslice, :==, :===, :dump, :=~, :downcase, :[], :[]=, :upcase, :downcase!, :capitalize, :swapcase, :upcase!, :oct, :empty?, :eql?, :hex, :chars, :split, :capitalize!, :swapcase!, :concat, :codepoints, :reverse, :lines, :bytes, :prepend, :scan, :ord, :reverse!, :center, :sub, :freeze, :inspect, :intern, :end_with?, :gsub, :chop, :crypt, :gsub!, :start_with?, :rstrip, :sub!, :ljust, :length, :size, :strip!, :succ, :rstrip!, :chomp, :strip, :rjust, :lstrip!, :tr!, :chomp!, :squeeze, :lstrip, :tr_s!, :to_str, :to_sym, :chop!, :each_byte, :each_char, :each_codepoint, :to_s, :to_i, :tr_s, :delete, :encoding, :force_encoding, :sum, :delete!, :squeeze!, :tr, :to_f, :valid_encoding?, :slice, :slice!, :rpartition, :each_line, :b, :ascii_only?, :hash, :to_r, :to_json, :to_json_raw, :to_json_raw_object, :<, :>, :<=, :>=, :between?, :pry, :__binding__, :pretty_print, :pretty_print_cycle, :pretty_print_instance_variables, :pretty_print_inspect, :instance_of?, :public_send, :instance_variable_get, :instance_variable_set, :instance_variable_defined?, :remove_instance_variable, :private_methods, :kind_of?, :instance_variables, :tap, :define_singleton_method, :is_a?, :extend, :to_enum, :enum_for, :pretty_inspect, :!~, :respond_to?, :display, :object_id, :send, :gem, :method, :public_method, :singleton_method, :nil?, :class, :singleton_class, :clone, :dup, :itself, :taint, :tainted?, :untaint, :untrust, :trust, :untrusted?, :methods, :protected_methods, :frozen?, :public_methods, :singleton_methods, :!, :!=, :__send__, :equal?, :instance_eval, :instance_exec, :__id__]\n",
      "singletonメソッド\n",
      "[]\n"
     ]
    }
   ],
   "source": [
    "a = \"foo\"\n",
    "\n",
    "puts \"publicメソッドとprivateメソッド\"\n",
    "puts a.methods\n",
    "puts \"privateメソッド\"\n",
    "puts a.private_methods\n",
    "puts \"protectedメソッド\"\n",
    "puts a.protected_methods\n",
    "puts \"publicメソッド\"\n",
    "puts a.public_methods\n",
    "puts \"singletonメソッド\"\n",
    "puts a.singleton_methods"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "## オブジェクトの複製\n",
    "\n",
    "* コピーするもの\n",
    "    * dup\n",
    "        * 汚染状態\n",
    "        * インスタンス変数\n",
    "        * ファイナライザ\n",
    "    * clone\n",
    "        * 汚染状態\n",
    "        * インスタンス変数\n",
    "        * ファイナライザ\n",
    "        * 凍結状態\n",
    "        * 特異メソッド\n",
    "* コピーの種類\n",
    "    * シャローコピー(浅いコピー)\n",
    "        * 自分自身の複製のみ\n",
    "        * 例えば、配列の要素の参照先は複製できない\n",
    " \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "70121692633620\n",
      "70121692633600\n"
     ]
    }
   ],
   "source": [
    "a = \"foo\"\n",
    "b = a.dup\n",
    "\n",
    "puts a.object_id\n",
    "puts b.object_id"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "## インスタンス変数へのアクセス"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[:@hoge]\n",
      "1\n",
      "3\n"
     ]
    }
   ],
   "source": [
    "class Foo\n",
    "  def initialize\n",
    "    @hoge = 1\n",
    "  end\n",
    "end\n",
    "\n",
    "foo = Foo.new\n",
    "\n",
    "puts foo.instance_variables\n",
    "\n",
    "### インスタンス変数は文字列(\"@hoge\")かシンボル(:@hoge)で指定\n",
    "puts foo.instance_variable_get(:@hoge)\n",
    "foo.instance_variable_set(:@hoge, 3)\n",
    "puts foo.instance_variable_get(:@hoge)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "## 未定義メソッドの呼び出し"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "hoge\n"
     ]
    }
   ],
   "source": [
    "class Bar\n",
    "#   def method_missing(name, *args)\n",
    "#     puts name\n",
    "#   end\n",
    "end\n",
    "\n",
    "c = Bar.new\n",
    "c.hoge\n",
    "\n",
    "#hoge"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "## オブジェクトの文字列表現\n",
    "\n",
    "* to_s\n",
    "    * 内容や値の文字列表現を返す\n",
    "* inspect\n",
    "    * オブジェクトを人が読める形に整形"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 66,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1.2\n",
      "1.2\n",
      "#<Foo:0x007f8cf4ac3db0>\n",
      "#<Foo:0x007f8cf4ac2ca8 @hoge=1, @fuga=2>\n"
     ]
    }
   ],
   "source": [
    "a = 1.2\n",
    "puts a.to_s\n",
    "puts a.inspect\n",
    "\n",
    "class Foo\n",
    "  def initialize\n",
    "    @hoge = 1\n",
    "    @fuga = 2\n",
    "  end\n",
    "end\n",
    "\n",
    "puts Foo.new.to_s\n",
    "puts Foo.new.inspect"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "### 特別なオブジェクト"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 71,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "20\n",
      "0\n",
      "8\n"
     ]
    }
   ],
   "source": [
    "puts true.object_id\n",
    "puts false.object_id\n",
    "puts nil.object_id"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Ruby 2.3.1",
   "language": "ruby",
   "name": "ruby"
  },
  "language_info": {
   "file_extension": ".rb",
   "mimetype": "application/x-ruby",
   "name": "ruby",
   "version": "2.3.1"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
